package com.kuang.productConsumer;

/**
 * 线程之间的通信问题：生产者消费者  （一个窗口，一次放一碗饭饭，阿姨这边打饭，同学这边拿饭）
 * 线程交替执行 A B 线程操作同一个变量  等待唤醒 wait，通知唤醒 notify
 * A num+1
 * B num-1
 *
 * A B 线程交替打印
 *
 * @author sdm
 * @version 1.0
 * @date 2023/6/24 11:12
 */
public class ProducerConsumerDemoAB {
    public static void main(String[] args) {

        // 1.准备资源类
        Goods goods = new Goods();

        // 2.创建多线程， 3.将资源类抛进去
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    goods.increment();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();  // A线程+1
        new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    goods.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();  // B线程-1
        // 预期结果：A=>1   B=>0   A=>1   B=>0  ...
        /*
           为什么出现交替打印结果？
                A=>1
                B=>0
                A=>1
                B=>0
                A=>1
                B=>0
                A=>1
                B=>0
                A=>1
                B=>0
                A=>1
            线程A，判断number是否等于0，等于0，干活+1，然后唤醒B，不等于0，等着
            线程B，判断number是否等于1，等于1，干活-1，然后唤醒A，不等于0，等着
         */


    }
}


/*
    资源类：饭  一个窗口
    生产者消费者问题：六字真言： （判断）等待、业务、通知
 */
class Goods{
    private int number = 0;

    //+1 生产了一件物品
    public synchronized void increment() throws InterruptedException {
        if (number != 0){   //O的时候，干活，不是0的时候，等待
            // 等待  窗口有一碗饭时，等会
            this.wait();
        }
        // 业务
        number ++;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        // 通知其他线程，我+1完毕了
        this.notifyAll();  // 通知唤醒其他线程
    }

    //-1 消费了一件物品
    public synchronized void decrement() throws InterruptedException {
        if (number == 0){   //1的时候，干活，不是1的时候，等待
            // 等待 窗口没有饭时，等会
            this.wait();
        }
        // 业务
        number --;
        System.out.println(Thread.currentThread().getName() + "=>" + number);
        // 通知其他线程，我-1完毕了
        this.notifyAll();  // 通知唤醒其他线程
    }
}
